package cn.portx.frame;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.bstek.bdf3.dorado.jpa.JpaUtil;
import com.bstek.bdf3.saas.SaasUtils;
import com.bstek.bdf3.saas.command.Command;
import com.bstek.bdf3.saas.domain.DataSourceInfo;
import com.bstek.bdf3.saas.domain.Organization;
import com.bstek.bdf3.saas.service.DataSourceService;
import com.bstek.bdf3.saas.service.EntityManagerFactoryService;
import com.bstek.bdf3.security.orm.User;
import com.bstek.dorado.annotation.DataProvider;
import com.bstek.dorado.annotation.DataResolver;
import com.bstek.dorado.annotation.Expose;
import com.bstek.dorado.data.entity.EntityState;
import com.bstek.dorado.data.entity.EntityUtils;
import com.bstek.dorado.data.provider.Criteria;
import com.bstek.dorado.data.provider.Page;

import cn.portx.frame.entity.Company;
import cn.portx.frame.entity.UserEntity;

@Component
public class CompanyPR {

	@Autowired
	private EntityManagerFactoryService entityManagerFactoryService;

	@Autowired
	private DataSourceService dataSourceService;
	
	@Autowired
	private PasswordEncoder passwordEncoder;

	@Autowired
	private com.bstek.bdf3.saas.service.OrganizationService organizationService;

	@DataProvider
	@Transactional
	public void loadCompany(Page<Company> page, Criteria criteria) {
		JpaUtil.linq(Company.class).collect(Organization.class, "orgId").where(criteria).desc("enable").asc("orgId").paging(page);
	}

	@DataProvider
	@Transactional
	public DataSourceInfo getDataSourceInfo(String dataSourceInfoId) {
		List<DataSourceInfo> list = JpaUtil.linq(DataSourceInfo.class).idEqual(dataSourceInfoId).list();
		return list == null || list.isEmpty() ? null : list.get(0);
	}

	@DataResolver
	@Transactional
	public void saveCompany(List<Company> companies) {
		for (Company c : companies) {
			EntityState state = EntityUtils.getState(c);
			if (state == EntityState.NEW) {
				this.insertCompany(c);
			} else if (state == EntityState.MODIFIED) {
				this.updateCompany(c);
			} else if (state == EntityState.DELETED) {
				this.deleteCompany(c);
			}
		}
	}

	public void insertCompany(Company c) {
		if ("1".equals(c.getEnable())) {
			Organization org = new Organization();
			org.setId(c.getOrgId());
			org.setName(c.getFullName());
			org.setDataSourceInfoId(EntityUtils.getString(c, "dataSourceInfoId"));
			JpaUtil.persist(org);
			c.setOrg(org);
			this.enable(org);
		}
		JpaUtil.persist(c);
	}

	@Expose
	@Transactional
	public String checkOrgUnique(String orgId) {
		if (JpaUtil.linq(Company.class).equal("orgId", orgId).count() > 0) {
			return "公司编码【" + orgId + "】已存在！";
		}
		return null;
	}

	private void updateCompany(Company c) {
		String oldEnable = EntityUtils.getOldString(c, "enable");
		if (!StringUtils.equals(oldEnable, c.getEnable())) {
			if ("1".equals(c.getEnable())) {
				//启用
				if (c.getOrg() == null) {
					Organization org = new Organization();
					org.setId(c.getOrgId());
					org.setName(c.getFullName());
					org.setDataSourceInfoId(EntityUtils.getString(c, "dataSourceInfoId"));
					JpaUtil.persist(org);
					c.setOrg(org);
					this.enable(org);
				} else {
					c.setEnable("1"); //2017-10-16 
//					this.enable(c.getOrg());
				}
			} else {
				//禁用
				if (c.getOrg() != null) {
					this.release(c.getOrg());
					//2017-10-16 下列三行注释掉
//					organizationService.releaseResource(c.getOrg());
//					JpaUtil.lind(Organization.class).idEqual(c.getOrgId()).delete();
//					JpaUtil.lind(UserEntity.class).equal("orgId", c.getOrgId()).delete();
				}
			}
		}
		JpaUtil.merge(c);
	}

	private void deleteCompany(Company c) {
		if (c.getOrg() != null) {
			this.release(c.getOrg());
			organizationService.releaseResource(c.getOrg());
			JpaUtil.lind(Organization.class).idEqual(c.getOrg().getId()).delete();
		}
		JpaUtil.lind(Company.class).idEqual(c.getId()).delete();
		JpaUtil.lind(UserEntity.class).equal("orgId", c.getOrgId()).delete();
	}

	/**
	 * 释放数据库资源
	 * 
	 * @param org
	 */
	private void release(Organization org) {
		EntityManagerFactory emf = entityManagerFactoryService.getEntityManagerFactory(org);
		DataSource ds = this.dataSourceService.getDataSource(org);
		this.entityManagerFactoryService.removeEntityManagerFactory(org);
		if (emf != null && emf.isOpen()) {
			emf.close();
		}
		if (ds != null) {
			//org.apache.tomcat.jdbc.pool.DataSource@39098de1{ConnectionPool[defaultAutoCommit=null; defaultReadOnly=null; defaultTransactionIsolation=-1; defaultCatalog=null; driverClassName=com.mysql.jdbc.Driver; maxActive=100; maxIdle=100; minIdle=10; initialSize=10; maxWait=30000; testOnBorrow=false; testOnReturn=false; timeBetweenEvictionRunsMillis=5000; numTestsPerEvictionRun=0; minEvictableIdleTimeMillis=60000; testWhileIdle=false; testOnConnect=false; password=********; url=jdbc:mysql://localhost:3306/CC0; username=root; validationQuery=null; validationQueryTimeout=-1; validatorClassName=null; validationInterval=3000; accessToUnderlyingConnectionAllowed=true; removeAbandoned=false; removeAbandonedTimeout=60; logAbandoned=false; connectionProperties=null; initSQL=null; jdbcInterceptors=null; jmxEnabled=true; fairQueue=true; useEquals=true; abandonWhenPercentageFull=0; maxAge=0; useLock=false; dataSource=null; dataSourceJNDI=null; suspectTimeout=0; alternateUsernameAllowed=false; commitOnReturn=false; rollbackOnReturn=false; useDisposableConnectionFacade=true; logValidationErrors=false; propagateInterruptState=false; ignoreExceptionOnPreLoad=false; useStatementFacade=true; }
			if (ds instanceof org.apache.tomcat.jdbc.pool.DataSource) {
				org.apache.tomcat.jdbc.pool.DataSource dataSource = (org.apache.tomcat.jdbc.pool.DataSource) ds;
				dataSource.close(true);
			}
		}
	}

	private void enable(Organization org) {
		organizationService.allocteResource(org);
		List<UserEntity> list = JpaUtil.linq(UserEntity.class).equal("orgId", org.getId()).list();
		//===============================================================
		/**
		 * 2017-09-28
		 * 
		 */
//		String account = org.getId();
//		String password = "111111";
//		String name = "测试用户";
//		UserEntity user = new UserEntity();
//		user.setAdministrator(true);
//		user.setAccountNonExpired(true);
//		user.setAccountNonLocked(true);
//		user.setCredentialsNonExpired(true);
//		user.setCredentialsNonExpired(true);
//		user.setUsername(account);
//		user.setNickname(name);
//		user.setPassword(this.passwordEncoder.encode(password));
//		user.setOrgId(org.getId());
//		JpaUtil.persist(user);
//		list.add(user);
		
		
		//===============================================================
		SaasUtils.doNonQuery(org.getId(), new Command() {

			@Override
			public void execute() {
				List<User> users = new ArrayList<User>();
				for (UserEntity userEntity : list) {
					User u = new User();
					u.setAccountNonExpired(userEntity.isAccountNonExpired());
					u.setAccountNonLocked(userEntity.isAccountNonLocked());
					u.setAdministrator(userEntity.isAdministrator());
					u.setEnabled(userEntity.isEnabled());
					u.setNickname(userEntity.getNickname());
					u.setOrganization(org);
					u.setPassword(userEntity.getPassword());
					u.setUsername(userEntity.getUsername());
					users.add(u);
				}
				JpaUtil.persist(users);
			}
		});

		this.release(org);

	}
}
